

#include <kernel/kernel.h>
#include <kernel/block/block.h>
#include <kernel/userid/userid.h>
#include <kernel/handle/handle.h>

#include "lua-5.1.1/include/lua.h"

userid ID;
handle In;
handle Out;
handle Error;

void *allocator (void *_ud, void *_ptr, size _osize, size _nsize)
{
	(void) _ud;

	if (_nsize == 0)
	{
		block_release (_ptr);

		return NULL;
	}
	else if (_osize == 0)
	{
		return block_request (_nsize);
	}
	else
	{
		return block_resize (_ptr, _nsize);
	}

}


const char *reader (lua_State *L, void *_data, size *_size)
{
	static char buf [256];

	(void) _data;

	*_size = handle_read (In, buf, 256);
	buf [*_size] = '\0';

	if (*_size == 0)
	{
		return NULL;
	}
	else
	{
		return buf;
	}
}


int shell_init ()
{
	lua_State *L;

	ID = userid_request ();

	In = handle_request ("system.shell.in", ID);
	Out = handle_request ("system.shell.out", ID);
	Error = handle_request ("system.shell.error", ID);

	if (handle_trylock (Out) != 0)
	{
		handle_release (In);
		handle_release (Out);
		handle_release (Error);
		userid_release (ID);

		return -1;
	}

	L = lua_newstate (allocator, NULL);
	luaL_openlibs (L);

	if (lua_load (L, reader, NULL, "system.shell.in") != 0)
	{
		handle_write (Error, lua_tostring (L, -1), lua_objlen (L, -1) + 1);
	}
	else if (lua_pcall (L, 0, 0, 0) != 0)
	{
		handle_write (Error, lua_tostring (L, -1), lua_objlen (L, -1) + 1);
	}

	lua_close (L);

	handle_release (In);
	handle_unlock (Out);
	handle_release (Out);
	userid_release (ID);
}
